package com.corn.juc.lock.custome;

import lombok.SneakyThrows;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @author : Jim Wu
 * @version 1.0
 * @function :
 * @since : 2020/12/29 15:35
 */

public class MySpinLock {

    AtomicReference<Thread> atomicReference = new AtomicReference<>();

    public void getLock() {
        // CAS 判断如果当前atomicReference中不为null说明被其他线程占用 返回false 取反一直自旋,一直到其他线程释放
        while (!atomicReference.compareAndSet(null, Thread.currentThread())) {

        }
        System.out.println(Thread.currentThread().getName() + "\t lock");
    }

    public void unlock() {
        // 解锁 用完了之后 CAS 当将当前进程置为null
        atomicReference.compareAndSet(Thread.currentThread(), null);
        System.out.println(Thread.currentThread().getName() + "\t unlock");
    }

    public static void main(String[] args) {
        MySpinLock lock = new MySpinLock();

        new Thread() {
            @SneakyThrows
            @Override
            public void run() {
                lock.getLock();
                System.out.println(Thread.currentThread().getName() + " enter !");
                TimeUnit.SECONDS.sleep(5);
                lock.unlock();
            }
        }.start();

        new Thread() {
            @SneakyThrows
            @Override
            public void run() {
                lock.getLock();
                System.out.println(Thread.currentThread().getName() + " enter !");
                lock.unlock();
            }
        }.start();

    }
}
